package util

import (
	"io/ioutil"
	"encoding/json"
	"bytes"
	"compress/gzip"
	"github.com/ngaut/log"
	"os"
	"github.com/shopspring/decimal"
	"time"
	"fmt"
	"path"
	"strings"
	"io"
	"net/http"
	"regexp"
)

// 将 USD 换算成 CNY
func GetUsdToCny(usd, rate string) string {
	usdDecimal, _ := decimal.NewFromString(usd)
	rateDecimal, _ := decimal.NewFromString(rate)
	return usdDecimal.Mul(rateDecimal).StringFixedBank(8)
}

func ImageUrl(imgUrl, fpath string) string {
	reg := regexp.MustCompile(`^http`)
	if len(reg.FindAllString(fpath, -1)) > 0 {
		return fpath
	}
	return path.Join(strings.TrimRight(imgUrl, "/"), "app", fpath)
}

// 下载图片
func DownloadImg(url string, name string, types string) (filePath string, err error) {
	var fname string
	var targetPrefix = "../../web"
	ext := path.Ext(url)
	if name == "" {
		fname = path.Base(url)
	} else {
		fname = name + ext
	}

	var size string
	paths := strings.Split(url, "/")
	if len(paths) > 2 {
		size = paths[len(paths)-2]
	}

	basePath := path.Join("static", "img", types, size)
	targetPath := path.Join(targetPrefix, basePath)
	if err = os.MkdirAll(targetPath, 0766); err != nil {
		return
	}

	filePath = fmt.Sprintf("%s/%s", basePath, fname)
	targetFilePath := fmt.Sprintf("%s/%s", targetPrefix, filePath)
	out, err := os.Create(targetFilePath)
	defer out.Close()

	resp, err := http.Get(url)
	defer resp.Body.Close()

	pix, err := ioutil.ReadAll(resp.Body)
	n, err := io.Copy(out, bytes.NewReader(pix))
	if n == 0 { filePath = "" }
	return
}

func JsonEncodeMapToByte(stringMap map[string]interface{}) []byte {
	jsonBytes, err := json.Marshal(stringMap)
	if err != nil {
		return nil
	}
	return jsonBytes
}

func JsonDecodeByte(bytes []byte) map[string]interface{} {
	jsonMap := make(map[string]interface{})
	json.Unmarshal(bytes, &jsonMap)
	return jsonMap
}

func UnGzip(byte []byte) ([]byte, error) {
	b := bytes.NewBuffer(byte)
	r, err := gzip.NewReader(b)
	if err != nil {
		return nil, err
	}
	defer func() {
		if r != nil {
			r.Close()
		}
	}()
	undatas, err := ioutil.ReadAll(r)
	if err != nil {
		return nil, err
	}
	return undatas, nil
}

func ErrorAndExit(format string, args ...interface{})  {
	log.Errorf(format, args...)
	os.Exit(1)
}


var timeTypeMaps = map[string]int{
	"1min":  1,
	"3min":  2,
	"5min":  5,
	"15min": 15,
	"30min": 30,
	"1hour":  1,
	"2hour":  2,
	"4hour":  4,
	"6hour":  6,
	"12hour": 12,
	"1day":  1,
	"3day":  3,
	"1week":  1,
	"1mon":  1,
	"1year": 1,
}

func FormatTimeToInterval(timestamp int64, ts string) int64 {

	in, ok := timeTypeMaps[ts]

	if !ok {
		return 0
	}

	var ftime string
	stamp := time.Unix(timestamp, 0)

	switch ts {
	case "1min":
		ftime = stamp.Format("2006-01-02 15:04:00")
	case "30min", "15min", "5min", "3min":
		i := stamp.Minute()
		c := i - i%in
		if c == 0 {
			ftime = stamp.Format("2006-01-02 15:00:00")
		} else {
			suffix := fmt.Sprintf("%d", c)
			if c < 10 {
				suffix = fmt.Sprintf("0%d", c)
			}
			ftime = stamp.Format("2006-01-02 15") + ":" + suffix + ":00"
		}
	case "12hour", "6hour", "4hour", "2hour", "1hour":
		h := stamp.Hour()
		c := h - h%in
		if c == 0 {
			ftime = stamp.Format("2006-01-02 00:00:00")
		} else {
			suffix := fmt.Sprintf("%d", c)
			if c < 10 {
				suffix = fmt.Sprintf("0%d", c)
			}
			ftime = stamp.Format("2006-01-02 ") + suffix + ":00:00"
		}
	case "1day":
		ftime = stamp.Format("2006-01-02 00:00:00")
	case "3day":
		yearDay := stamp.YearDay()
		c := yearDay % 3
		ftime = stamp.Add(-1 * time.Duration(c) * time.Hour).Format("2006-01-02 00:00:00")
	case "1week":
		w := time.Unix(timestamp, 0).Weekday()
		ftime = stamp.Add(-1 * time.Duration(w) * time.Hour).Format("2006-01-02 00:00:00")
	case "1mon":
		year, month, _ := stamp.Date()
		ftime = time.Date(year, month, 1, 0, 0, 0, 0, time.Local).Format("2006-01-02 15:04:05")
	}

	p, err := time.ParseInLocation("2006-01-02 15:04:05", ftime, time.Local)
	if err != nil {
		log.Errorf("parse time error: %s", err.Error())
		return 0
	}

	return p.Unix()
}

func GetSum(o, n string) string {
	oldP, _ := decimal.NewFromString(o)
	newP, _ := decimal.NewFromString(n)
	return oldP.Add(newP).String()
}

// 比较得到较大值
func GetGreater(oldP, newP string) string {
	o, _ := decimal.NewFromString(oldP)
	n, _ := decimal.NewFromString(newP)
	if o.GreaterThan(n) {
		return oldP
	}
	return newP
}


